package com.jacob.androidframe.base;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.text.TextUtils;

/**
 * 本类是PagerAdapter类的子类，专门用于在ViewPager中显示Fragment。
 * 本类适用于Fragment的数量较少的情况。
 * 本类会将可不见的Fragment隐藏，但不会将其删除，所以占用内存可能较多（Fragment数量太多时，可能会造成内存溢出），但是加载速度也较快。
 * 
 * 如果Fragment数量较多（超过10个），请考虑使用AdapterPagerFragmentStateBase类，以节约宝贵的内存。
 * 
 * 注1：使用这个Adapter的ViewPager必须有合法的ID。
 * 注2：为了使notifyDataSetChanged()方法既能够刷新Page的顺序，也能刷新Fragment的内容，必须满足以下几个条件（具体可查看checkList()方法的代码）：
 * 1. Fragment必须继承FragmentForViewPagerBase类。
 * 2. Fragment必须包含有效的、唯一的CustomId。
 */
public class AdapterPagerFragmentBase extends FragmentPagerAdapter
{
	private Context mContext;
	private List<AbstractItem> mItemList;

	public AdapterPagerFragmentBase(Context pContext, FragmentManager pFragmentManager)
	{
		this(pContext, pFragmentManager, null);
	}

	public AdapterPagerFragmentBase(Context pContext, FragmentManager pFragmentManager, List<AbstractItem> pItemList)
	{
		super(pFragmentManager);
		mContext = pContext;
		setItemList(pItemList);
	}

	@Override
	public int getCount()
	{
		return mItemList.size();
	}

	@Override
	public long getItemId(int pPosition)
	{
		return mItemList.get(pPosition).getBundleArgs().getLong(FragmentForViewPagerBase.BUNDLE_KEY_CUSTOM_ID_LONG, FragmentForViewPagerBase.INVALID_CUSTOM_ID);
	}

	/**
	 * 当调用notifyDataSetChanged()方法时，ViewPager会调用本方法来决定每个Page是否要改变位置。
	 * 本方法覆盖了父类的实现，让刷新位置的同时，也会刷新Fragment。
	 */
	@Override
	public int getItemPosition(Object pObject)
	{
		FragmentForViewPagerBase _Fragment = (FragmentForViewPagerBase) pObject;
		long _Id = _Fragment.getCustomId();
	
		for (AbstractItem _Item : mItemList) {
			if (_Id == _Item.getBundleArgs().getLong(FragmentForViewPagerBase.BUNDLE_KEY_CUSTOM_ID_LONG)) {
				_Fragment.onRefresh(_Item.getBundleArgs());
				return mItemList.indexOf(_Item);
			} else {
				continue;
			}
		}
	
		return POSITION_NONE;
	}

	@Override
	public CharSequence getPageTitle(int pPosition)
	{
		CharSequence _PageTitle = mItemList.get(pPosition).getPageTitle();
		if (!TextUtils.isEmpty(_PageTitle)) {
			return _PageTitle;
		} else {
			return "";
		}
	}

	@Override
	public Fragment getItem(int pPosition)
	{
		Class<? extends FragmentForViewPagerBase> _FragmentClass = mItemList.get(pPosition).getFragmentClass();
		Bundle _BundleArgs = mItemList.get(pPosition).getBundleArgs();

		return FragmentForViewPagerBase.instantiate(getContext(), _FragmentClass.getName(), _BundleArgs);
	}

	@Override
	public void notifyDataSetChanged()
	{
		if (!checkList()) {
			throw new IllegalArgumentException("Unable to instantiate fragment. Please read " + getClass() + "'s Java doc. ");
		}
		super.notifyDataSetChanged();
	}

	public void setItemList(List<AbstractItem> pItemList)
	{
		if (pItemList == null) {
			mItemList = new ArrayList<AbstractItem>();
		} else {
			mItemList = new ArrayList<AbstractItem>(pItemList);
		}
		notifyDataSetChanged();
	}

	public void addItem(AbstractItem pItem)
	{
		if (pItem != null) {
			mItemList.add(pItem);
		}
		notifyDataSetChanged();
	}

	public void addItem(int pPosition, AbstractItem pItem)
	{
		if (pItem != null) {
			mItemList.add(pPosition, pItem);
		}
		notifyDataSetChanged();
	}

	public void addItemList(List<AbstractItem> pItemList)
	{
		if (pItemList != null) {
			mItemList.addAll(pItemList);
		}
		notifyDataSetChanged();
	}

	public void addItemList(int pPosition, List<AbstractItem> pItemList)
	{
		if (pItemList != null) {
			mItemList.addAll(pPosition, pItemList);
		}
		notifyDataSetChanged();
	}

	public void removeItem(int pPosition)
	{
		mItemList.remove(pPosition);
		notifyDataSetChanged();
	}

	
	
	
	
	
	
	protected Context getContext()
	{
		return mContext;
	}

	private boolean checkList()
	{
		// 检查ItemList是否为null
		if (mItemList == null) {
			return false;
		}
	
		// 检查ItemList中的数据
		for (AbstractItem _Item : mItemList) {
			// 检查Item是否为null
			if (_Item == null) {
				return false;
			}
			// 检查Item中的数据是否为null
			if (_Item.getFragmentClass() == null || _Item.getBundleArgs() == null) {
				return false;
			}
			// 检查Bundle中是否设置了有效的CustomId
			long _FragmentCustomId = _Item.getBundleArgs().getLong(FragmentForViewPagerBase.BUNDLE_KEY_CUSTOM_ID_LONG, FragmentForViewPagerBase.INVALID_CUSTOM_ID);
			if (FragmentForViewPagerBase.INVALID_CUSTOM_ID == _FragmentCustomId) {
				return false;
			}
		}
	
		// 检查mAbstractItemList中的CustomId是否重复
		for (int i = 0; i < mItemList.size(); i++) {
			long _FragmentCustomId1 = mItemList.get(i).getBundleArgs().getLong(FragmentForViewPagerBase.BUNDLE_KEY_CUSTOM_ID_LONG);
			for (int j = i + 1; j < mItemList.size(); j++) {
				long _FragmentCustomId2 = mItemList.get(j).getBundleArgs().getLong(FragmentForViewPagerBase.BUNDLE_KEY_CUSTOM_ID_LONG);
				if (_FragmentCustomId1 == _FragmentCustomId2) {
					return false;
				}
			}
		}
	
		return true;
	}

	public static class AbstractItem
	{
		private CharSequence mPageTitle;
		private Class<? extends FragmentForViewPagerBase> mFragmentClass;
		private Bundle mBundleArgs;

		public AbstractItem(CharSequence pPageTitle, Class<? extends FragmentForViewPagerBase> pFragmentClass, Bundle pBundleArgs)
		{
			setPageTitle(pPageTitle);
			setFragmentClass(pFragmentClass);
			setBundleArgs(pBundleArgs);
		}

		public CharSequence getPageTitle() {
			return mPageTitle;
		}

		public void setPageTitle(CharSequence pPageTitle) {
			mPageTitle = pPageTitle;
		}

		public Class<? extends FragmentForViewPagerBase> getFragmentClass()
		{
			return mFragmentClass;
		}

		public void setFragmentClass(Class<? extends FragmentForViewPagerBase> pFragmentClass)
		{
			mFragmentClass = pFragmentClass;
		}

		public Bundle getBundleArgs()
		{
			return mBundleArgs;
		}

		public void setBundleArgs(Bundle pBundleArgs)
		{
			mBundleArgs = pBundleArgs;
		}
	}
}
